/*
author:杨文超
email:yangwenchao@keynection.cn
*/

/*modbus master协议栈初始化*/
#pragma once


#include "mbconfig.h"
#include "mbport.h"

#ifdef __cplusplus
extern "C" {
#endif

#include "mbport.h"
#include "mbproto.h"
/*
This module defines the interface for the application. It contains
the basic functions and types required to use the Modbus Master protocol stack.
A typical application will want to call eMBMasterInit() first. If the device
is ready to answer network requests it must then call eMBEnable() to activate
the protocol stack. In the main loop the function eMBMasterPoll() must be called
periodically. The time interval between pooling depends on the configured
Modbus timeout. If an RTOS is available a separate task should be created
and the task should always call the function eMBMasterPoll().
*/

/*
This value is passed to the callback functions which support either
reading or writing register values. Writing means that the application
registers should be updated and reading means that the modbus protocol
stack needs to know the current register values.
see eMBRegHoldingCB( ), eMBRegCoilsCB( ), eMBRegDiscreteCB( ) and
eMBRegInputCB( ).
*/
typedef enum
{
    MB_REG_READ,                /* Read register values and pass to protocol stack. */
    MB_REG_WRITE                /* Update register values. */
} eMBRegisterMode;

/*
Errorcodes used by all function in the protocol stack.
*/
typedef enum
{
    MB_ENOERR,                  /* no error. */
    MB_ENOREG,                  /* illegal register address. */
    MB_EINVAL,                  /* illegal argument. */
    MB_EPORTERR,                /* porting layer error. */
    MB_ENORES,                  /* insufficient resources. */
    MB_EIO,                     /* I/O error. */
    MB_EILLSTATE,               /* protocol stack in illegal state. */
    MB_ETIMEDOUT                /* timeout error occurred. */
} eMBErrorCode;



/*
Errorcodes used by all function in the Master request.
*/
typedef enum
{
    MB_MRE_NO_ERR,                  /* no error. */
    MB_MRE_NO_REG,                  /* illegal register address. */
    MB_MRE_ILL_ARG,                 /* illegal argument. */
    MB_MRE_REV_DATA,                /* receive data error. */
    MB_MRE_TIMEDOUT,                /* timeout error occurred. */
    MB_MRE_MASTER_BUSY,             /* master is busy now. */
    MB_MRE_EXE_FUN                  /* execute function error. */
} eMBMasterReqErrCode;

/*
TimerMode is Master 3 kind of Timer modes.
*/
typedef enum
{
	MB_TMODE_T35,                   /* Master receive frame T3.5 timeout. */
	MB_TMODE_RESPOND_TIMEOUT,       /* Master wait respond for slave. */
	MB_TMODE_CONVERT_DELAY          /* Master sent broadcast ,then delay sometime.*/
} eMBMasterTimerMode;

/*
Initialize the Modbus Master protocol stack.

This functions initializes RTU module and calls the
init functions of the porting layer to prepare the hardware. Please
note that the receiver is still disabled and no Modbus frames are
processed until eMBMasterEnable( ) has been called.

@param eMode If RTU mode should be used.
@param ucPort The port to use. 
@param ulBaudRate The baudrate. E.g. 19200. Supported baudrates depend
on the porting layer.
@param eParity Parity used for serial transmission.

@return If no error occurs the function returns eMBErrorCode::MB_ENOERR.
The protocol is then in the disabled state and ready for activation
by calling eMBMasterEnable( ). Otherwise one of the following error codes
is returned: eMBErrorCode::MB_EPORTERR IF the porting layer returned an error.
*/
eMBErrorCode    eMBMasterSerialInit(UCHAR ucPort,
		                 ULONG ulBaudRate, eMBParity eParity );

/*
Release resources used by the protocol stack.

This function disables the Modbus Master protocol stack and release all
hardware resources. It must only be called when the protocol stack
is disabled.

@note Note all ports implement this function. A port which wants to
get an callback must define the macro MB_PORT_HAS_CLOSE to 1.

@return If the resources where released it return eMBErrorCode::MB_ENOERR.
If the protocol stack is not in the disabled state it returns
eMBErrorCode::MB_EILLSTATE.
*/
eMBErrorCode    eMBMasterClose( void );

/*
Enable the Modbus Master protocol stack.

This function enables processing of Modbus Master frames. Enabling the protocol
stack is only possible if it is in the disabled state.

@return If the protocol stack is now in the state enabled it returns
eMBErrorCode::MB_ENOERR. If it was not in the disabled state it
return eMBErrorCode::MB_EILLSTATE.
*/
eMBErrorCode    eMBMasterEnable( void );

/*
Disable the Modbus Master protocol stack.

This function disables processing of Modbus frames.

@return If the protocol stack has been disabled it returns
eMBErrorCode::MB_ENOERR. If it was not in the enabled state it returns
eMBErrorCode::MB_EILLSTATE.
*/
eMBErrorCode    eMBMasterDisable( void );

/*
The main pooling loop of the Modbus Master protocol stack.

This function must be called periodically. The timer interval required
is given by the application dependent Modbus slave timeout. Internally the
function calls xMBMasterPortEventGet() and waits for an event from the receiver or
transmitter state machines.

@return If the protocol stack is not in the enabled state the function
returns eMBErrorCode::MB_EILLSTATE. Otherwise it returns
eMBErrorCode::MB_ENOERR.
*/
eMBErrorCode    eMBMasterPoll( void );

/*
Registers a callback handler for a given function code.

This function registers a new callback handler for a given function code.
The callback handler supplied is responsible for interpreting the Modbus PDU and
the creation of an appropriate response. In case of an error it should return
one of the possible Modbus exceptions which results in a Modbus exception frame
sent by the protocol stack.

@param ucFunctionCode The Modbus function code for which this handler should
be registers. Valid function codes are in the range 1 to 127.
@param pxHandler The function handler which should be called in case
such a frame is received. If  NULL a previously registered function handler
for this function code is removed.

@return eMBErrorCode::MB_ENOERR if the handler has been installed. If no
more resources are available it returns eMBErrorCode::MB_ENORES. In this
case the values in mbconfig.h should be adjusted. If the argument was not
valid it returns eMBErrorCode::MB_EINVAL.
*/
eMBErrorCode    eMBMasterRegisterCB( UCHAR ucFunctionCode,
                               pxMBFunctionHandler pxHandler );

/*modbus_master registers Modbus Registers

The protocol stack does not internally allocate any memory for the
registers. This makes the protocol stack very small and also usable on
low end targets. In addition the values don't have to be in the memory
and could for example be stored in a flash.
Whenever the protocol stack requires a value it calls one of the callback
function with the register address and the number of registers to read
as an argument. The application should then read the actual register values
for example the ADC voltage) and should store the result in the supplied
buffer.
If the protocol stack wants to update a register value because a write
register function was received a buffer with the new register values is
passed to the callback function. The function should then use these values
to update the application register values.
*/

/*
Callback function used if the value of a <em>Input Register</em>
is required by the protocol stack. The starting register address is given
by usAddress and the last register is given by <tt>usAddress +
usNRegs - 1</tt>.

@param pucRegBuffer A buffer where the callback function should write
the current value of the modbus registers to.
@param usAddress The starting address of the register. Input registers
are in the range 1 - 65535.
@param usNRegs Number of registers the callback function must supply.

@return The function must return one of the following error codes:
   - eMBErrorCode::MB_ENOERR If no error occurred. In this case a normal
       Modbus response is sent.
   - eMBErrorCode::MB_ENOREG If the application does not map an coils
       within the requested address range. In this case a
       <b>ILLEGAL DATA ADDRESS</b> is sent as a response.
*/
eMBErrorCode eMBMasterRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress,
		USHORT usNRegs );

/*
Callback function used if a <em>Holding Register</em> value is
read or written by the protocol stack. The starting register address
is given by \c usAddress and the last register is given by
<tt>usAddress + usNRegs - 1</tt>.

@param pucRegBuffer If the application registers values should be updated the
buffer points to the new registers values. If the protocol stack needs
to now the current values the callback function should write them into
this buffer.
@param usAddress The starting address of the register.
@param usNRegs Number of registers to read or write.
@param eMode If eMBRegisterMode::MB_REG_WRITE the application register
values should be updated from the values in the buffer. For example
this would be the case when the Modbus master has issued an
<b>WRITE SINGLE REGISTER</b> command.
If the value eMBRegisterMode::MB_REG_READ the application should copy
the current values into the buffer \c pucRegBuffer.

@return The function must return one of the following error codes:
   - eMBErrorCode::MB_ENOERR If no error occurred. In this case a normal
       Modbus response is sent.
   - eMBErrorCode::MB_ENOREG If the application does not map an coils
       within the requested address range. In this case a
       <b>ILLEGAL DATA ADDRESS</b> is sent as a response.
*/
eMBErrorCode eMBMasterRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress,
		USHORT usNRegs, eMBRegisterMode eMode );

/*
Callback function used if a <em>Coil Register</em> value is
read or written by the protocol stack. If you are going to use
this function you might use the functions xMBUtilSetBits(  ) and
xMBUtilGetBits(  ) for working with bitfields.

@param pucRegBuffer The bits are packed in bytes where the first coil
starting at address \c usAddress is stored in the LSB of the
first byte in the buffer <code>pucRegBuffer</code>.
If the buffer should be written by the callback function unused
coil values (I.e. if not a multiple of eight coils is used) should be set
to zero.
@param usAddress The first coil number.
@param usNCoils Number of coil values requested.
@param eMode If eMBRegisterMode::MB_REG_WRITE the application values should
be updated from the values supplied in the buffer \c pucRegBuffer.
If eMBRegisterMode::MB_REG_READ the application should store the current
values in the buffer \c pucRegBuffer.

@return The function must return one of the following error codes:
   - eMBErrorCode::MB_ENOERR If no error occurred. In this case a normal
       Modbus response is sent.
   - eMBErrorCode::MB_ENOREG If the application does not map an coils
       within the requested address range. In this case a
       <b>ILLEGAL DATA ADDRESS</b> is sent as a response.
*/
eMBErrorCode eMBMasterRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress,
		USHORT usNCoils, eMBRegisterMode eMode );

/*
Callback function used if a <em>Input Discrete Register</em> value is
read by the protocol stack.

If you are going to use his function you might use the functions
xMBUtilSetBits(  ) and xMBUtilGetBits(  ) for working with bitfields.

@param pucRegBuffer The buffer should be updated with the current
coil values. The first discrete input starting at \c usAddress must be
stored at the LSB of the first byte in the buffer. If the requested number
is not a multiple of eight the remaining bits should be set to zero.
@param usAddress The starting address of the first discrete input.
@param usNDiscrete Number of discrete input values.
@return The function must return one of the following error codes:
   - eMBErrorCode::MB_ENOERR If no error occurred. In this case a normal
       Modbus response is sent.
   - eMBErrorCode::MB_ENOREG If the application does not map an coils
       within the requested address range. In this case a
       <b>ILLEGAL DATA ADDRESS</b> is sent as a response.
*/
eMBErrorCode eMBMasterRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress,
		USHORT usNDiscrete );

/*
These Modbus functions are called for user when Modbus run in Master Mode.
*/
eMBMasterReqErrCode
eMBMasterReqReadInputRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usNRegs, LONG lTimeOut );
eMBMasterReqErrCode
eMBMasterReqWriteHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usRegData, LONG lTimeOut );
eMBMasterReqErrCode
eMBMasterReqWriteMultipleHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr,
		USHORT usNRegs, USHORT * pusDataBuffer, LONG lTimeOut );
eMBMasterReqErrCode
eMBMasterReqReadHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usNRegs, LONG lTimeOut );
eMBMasterReqErrCode
eMBMasterReqReadWriteMultipleHoldingRegister( UCHAR ucSndAddr,
		USHORT usReadRegAddr, USHORT usNReadRegs, USHORT * pusDataBuffer,
		USHORT usWriteRegAddr, USHORT usNWriteRegs, LONG lTimeOut );
eMBMasterReqErrCode
eMBMasterReqReadCoils( UCHAR ucSndAddr, USHORT usCoilAddr, USHORT usNCoils, LONG lTimeOut );
eMBMasterReqErrCode
eMBMasterReqWriteCoil( UCHAR ucSndAddr, USHORT usCoilAddr, USHORT usCoilData, LONG lTimeOut );
eMBMasterReqErrCode
eMBMasterReqWriteMultipleCoils( UCHAR ucSndAddr,
		USHORT usCoilAddr, USHORT usNCoils, UCHAR * pucDataBuffer, LONG lTimeOut );
eMBMasterReqErrCode
eMBMasterReqReadDiscreteInputs( UCHAR ucSndAddr, USHORT usDiscreteAddr, USHORT usNDiscreteIn, LONG lTimeOut );

eMBException
eMBMasterFuncReportSlaveID( UCHAR * pucFrame, USHORT * usLen );
eMBException
eMBMasterFuncReadInputRegister( UCHAR * pucFrame, USHORT * usLen );
eMBException
eMBMasterFuncReadHoldingRegister( UCHAR * pucFrame, USHORT * usLen );
eMBException
eMBMasterFuncWriteHoldingRegister( UCHAR * pucFrame, USHORT * usLen );
eMBException
eMBMasterFuncWriteMultipleHoldingRegister( UCHAR * pucFrame, USHORT * usLen );
eMBException
eMBMasterFuncReadCoils( UCHAR * pucFrame, USHORT * usLen );
eMBException
eMBMasterFuncWriteCoil( UCHAR * pucFrame, USHORT * usLen );
eMBException
eMBMasterFuncWriteMultipleCoils( UCHAR * pucFrame, USHORT * usLen );
eMBException
eMBMasterFuncReadDiscreteInputs( UCHAR * pucFrame, USHORT * usLen );
eMBException
eMBMasterFuncReadWriteMultipleHoldingRegister( UCHAR * pucFrame, USHORT * usLen );

/*
These functions are interface for Modbus Master
*/
void vMBMasterGetPDUSndBuf( UCHAR ** pucFrame );
UCHAR ucMBMasterGetDestAddress( void );
void vMBMasterSetDestAddress( UCHAR Address );
BOOL xMBMasterGetCBRunInMasterMode( void );
void vMBMasterSetCBRunInMasterMode( BOOL IsMasterMode );
USHORT usMBMasterGetPDUSndLength( void );
void vMBMasterSetPDUSndLength( USHORT SendPDULength );
void vMBMasterSetCurTimerMode( eMBMasterTimerMode eMBTimerMode );
void vMBMasterRequestSetType( BOOL xIsBroadcast );
eMBMasterTimerMode xMBMasterGetCurTimerMode( void );
BOOL xMBMasterRequestIsBroadcast( void );
eMBMasterErrorEventType eMBMasterGetErrorType( void );
void vMBMasterSetErrorType( eMBMasterErrorEventType errorType );
eMBMasterReqErrCode eMBMasterWaitRequestFinish( void );


#ifdef __cplusplus
}
#endif

